///
//  BaseFx v 1.0
//  Russell Lowke, Febrauary 26th 2011
//
//  Copyright (c) 2011 Lowke Media
//  see http://www.lowkemedia.com for more information
//
//  Permission is hereby granted, free of charge, to any person obtaining a 
//  copy of this software and associated documentation files (the "Software"), 
//  to deal in the Software without restriction, including without limitation 
//  the rights to use, copy, modify, merge, publish, distribute, sublicense, 
//  and/or sell copies of the Software, and to permit persons to whom the 
//  Software is furnished to do so, subject to the following conditions:
// 
//  The above copyright notice and this permission notice shall be included in 
//  all copies or substantial portions of the Software.
// 
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
//  IN THE SOFTWARE. 
//
//

function BaseFx(name, 							// (string) name of this effect
				type) 							// (string) how effect behaves when finished, BaseFx.PERSIST, BaseFx.WRAP, 
												//			BaseFx.REVERSE, BaseFx.END, or BaseFx.REMOVE.
{
    this.name = name;             				// (string) name of this effect
    this.type = type;             				// (string) effect type, PERSIST, WRAP, REVERSE, END, or REMOVE
    this.animatem;                   			// (Animatem) animator
    this.anime;                      			// (Anime) anime object owning effect
    this.target;                     			// (object) target object being affected
    this.startTime;                  			// (uint) time effect starts, might be time-stamped future or past time
    this.updateTime;                 			// (uint) time of update
    this.timePassed;                			// (uint) time since last update
    this.cycles;                    			// (uint) times to cycle before ending, undefined (default) means no cycling
    this.activated;                 			// (boolean) if false effect has not been activated yet

    this.initialize = function(animatem, anime, target, startTime)
    {
        this.animatem = animatem;
        this.anime = anime;
        this.target = target;
        this.startTime = startTime;
        
        // updateTime must be initialized to startTime
        this.updateTime = this.startTime;
    }
    
    
    this.resolve = function (updateTime) 
    {
        // calculate time passed since last update
        this.timePassed = updateTime - this.updateTime;
        
        // record time of update
        this.updateTime = updateTime;
        
        if (this.updateTime < this.startTime) {
            
            // this effect is not ready to trigger yet, exit
            return;
            
        } else if (this.timePassed >= 0 /* _interval */) {
        
            if (! this.activated) {
                this.activate();
                this.activated = true;
            }
            
            // perform effect
            var resolved = this.update();
            $(this).trigger($.Event(BaseFx.EFFECT_UPDATED_EVENT));
            
            if (resolved) {
    
                // check for cycling effects
                if (this.cycles !== undefined) {
                
                    --this.cycles;
                    if (this.cycles <= 0) {
                        this.type = BaseFx.END;
                    }
                    
                    // can't cycle end or remove types
                    if (this.type === BaseFx.END || 
                        this.type === BaseFx.REMOVE) {
                        this.cycles = undefined;
                    }
                }
                
                // when effect finishes
                switch (this.type) {
                    case BaseFx.PERSIST:                                        break;
                    case BaseFx.WRAP:   	this.wrap();                        break;
                    case BaseFx.REVERSE:	this.reverse();                  	break;
                    case BaseFx.PAUSE:		this.pause();                  		break;
                    case BaseFx.END:        this.anime.removeEffect(this);   break;
                    // case BaseFx.REMOVE:     this.anime.remove();             break;
                }
                
                // if finished and not cycling then dispatch event
                if (this.cycles === undefined) {
                    $(this).trigger($.Event(BaseFx.EFFECT_DONE_EVENT));
                }
            }
        }
    }
        
        
    //
    // functions for override
    this.activate = function() {
        // effcts need not have an activate() method
    }
    
    this.update = function() {
        throw new Error("Effect " + this.name + " must override update() method.");
    }
    
    this.cleanup = function() {
        // effects need not have a cleanup() method
    }
    
    this.wrap = function() {
        LogAs.warning("Effect " + this.name + " does not support cycle() method.", Animatem.WARNING_SNAP_TO_END_NOT_SUPPORTED);
    }
    
    this.reverse = function() {
        LogAs.warning("Effect " + this.name + " does not support reverse() method.", Animatem.WARNING_CYCLE_NOT_SUPPORTED);
    }
    
    this.pause = function() {
        LogAs.warning("Effect " + this.name + " does not support pause() method.", Animatem.WARNING_REVERSE_NOT_SUPPORTED);
    }
    
    this.unpause = function() {
        LogAs.warning("Effect " + this.name + " does not support unpause() method.", Animatem.WARNING_PAUSE_NOT_SUPPORTED);
    }
    
    /*
    //
    // print name of effect
    public override function toString():String {
        return _name; 
    }
    */
}


// events dispatched
BaseFx.EFFECT_DONE_EVENT = "effect_done_event";
BaseFx.EFFECT_UPDATED_EVENT = "effect_updated_event";

// constants for type
BaseFx.PERSIST    = "persist";				// maintain effect even though end conditions met
BaseFx.WRAP       = "wrap";					// wrap to beginning of effect and start over
BaseFx.REVERSE    = "reverse";				// play effecct in reverse
BaseFx.END        = "end";					// remove effect form the Anime
BaseFx.REMOVE     = "remove";				// remove Anime from Animatem
BaseFx.PAUSE      = "pause";        		// NEEDED?

    